﻿// <copyright file="DeploySWMM5.cs" company="City of Portland, BES-ASM">
// </copyright>
// <summary>DeploySWMM5 class</summary>

namespace BESASM.EMGAATS.DataAccess
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BESASM.EMGAATS.BusinessClasses;

  /// <summary>
  /// Manages deployment of a model to SWMM 5 format
  /// </summary>
  public class DeploySWMM5
  {
    private List<string> output = new List<string>();
    private List<Subcatchment> subcatchments = new List<Subcatchment>();

    /// <summary>
    /// Creates the SWMM 5 file
    /// </summary>
    /// <param name="simulation">The name of the simulation</param>
    /// <param name="model">The model being deployed</param>
    public void FillSWMM5List(ISimulation simulation, Model model)
    {
      if (!model.Simulations.Contains(simulation))
      {
        throw new ArgumentOutOfRangeException("simulation not in model");
      }

      Console.WriteLine("Begin build subcatchments");
      BuildSubcatchments bs = new BuildSubcatchments(model.Network);
      this.subcatchments = bs.Build();
      Console.WriteLine("End build subcatchments");
      
      this.output.Add("[TITLE]");
      this.output.Add(model.Name);
      this.output.Add(string.Empty);
      this.output.Add("[OPTIONS]");
      this.output.Add(";;Option             Value");
      this.output.Add("FLOW_UNITS           CFS");
      this.output.Add("INFILTRATION         HORTON");
      this.output.Add("FLOW_ROUTING         DYNWAVE");
      this.output.Add("LINK_OFFSETS         ELEVATION");
      this.output.Add("MIN_SLOPE            0");
      this.output.Add("ALLOW_PONDING        NO");
      this.output.Add("SKIP_STEADY_STATE    NO");
      this.output.Add(string.Format("START_DATE           {0:MM/dd/yyyy}", simulation.SimulationStartDateTime));
      this.output.Add(string.Format("START_TIME           {0:HH:mm:ss}", simulation.SimulationStartDateTime));
      this.output.Add(string.Format("REPORT_START_DATE    {0:MM/dd/yyyy}", simulation.ReportStartDateTime));
      this.output.Add(string.Format("REPORT_START_TIME    {0:HH:mm:ss}", simulation.ReportStartDateTime));
      this.output.Add(string.Format("END_DATE             {0:MM/dd/yyyy}", simulation.SimulationEndDateTime));
      this.output.Add(string.Format("END_TIME             {0:HH:mm:ss}", simulation.SimulationEndDateTime));
      this.output.Add(string.Format("REPORT_STEP          {0:HH:mm:ss}", simulation.ReportTimeStep));
      this.output.Add(string.Format("WET_STEP             {0:HH:mm:ss}", simulation.WetTimeStep));
      this.output.Add(string.Format("DRY_STEP             {0:HH:mm:ss}", simulation.DryTimeStep));
      this.output.Add(string.Format("ROUTING_STEP         {0:HH:mm:ss}", simulation.RoutingStep));

      this.output.Add(string.Empty);
      this.output.Add("[RAINGAGES]");
      this.output.Add(";;Gage           Format    Interval SCF      Source");
      this.output.Add(";;-------------- --------- ------ ------ ----------");
      // TODO: once the storm class is finalized loop through gages and put them here
      this.output.Add(@"1                INTENSITY 0:05     1.0      FILE       ""W:\SAMaster_22\rainfall\2.swmm5.dat"" 1          IN");

      this.output.Add(string.Empty);
      this.output.Add("[SUBCATCHMENTS]");
      this.output.Add(";;Subcatchment   Rain Gage        Outlet           Area     %Imperv  Width    %Slope   CurbLen  Snow Pack");
      this.output.Add(";;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ----------------");

      foreach (Subcatchment sc in this.subcatchments)
      {
        this.output.Add(
          string.Format(
          "{0,-16} {1,-16} {2,-16} {3,-8:F4} {4,-8:F2} {5,-8} {6,-8:F3} {7,-8} {8, -16}",
          sc.SubcatchmentName,
          1,
          sc.Node.NodeName,
          sc.AreaSqFt / 43560,
          100,
          sc.FlowLengthFt,
          sc.SlopeFtPerFt * 100,
          0,
          string.Empty));
      }

      this.output.Add(string.Empty);
      this.output.Add("[JUNCTIONS]");
      this.output.Add(";;Junction       Invert     Dmax       Dinit      Dsurch     Aponded   ");
      this.output.Add(";;-------------- ---------- ---------- ---------- ---------- ----------");
      
      foreach (INode n in model.Network.Nodes)
      {
        this.output.Add(
          string.Format(
          "{0,-16} {1,-10:F2} {2,-10:F2} {3,-10:F3} {4,-10:F2} {5,-10:F2}",
          n.NodeName,
          n.NodeIEFt,
          n.GroundElevFt - n.NodeIEFt,
          0,
          0,
          0));
      }

      this.output.Add(string.Empty);
      this.output.Add("[COORDINATES]");
      this.output.Add(";;Node           X-Coord            Y-Coord           ");
      this.output.Add(";;-------------- ------------------ ------------------");

      foreach (INode n in model.Network.Nodes)
      {
        this.output.Add(string.Format("{0,-16} {1,-18:F3} {2,-18:F3}", n.NodeName, n.X, n.Y));
      }

      this.output.Add(string.Empty);
      this.output.Add("[POLYGONS]");
      this.output.Add(";;Subcatchment   X-Coord            Y-Coord");
      this.output.Add(";;-------------- ------------------ ------------------");
      foreach (Subcatchment sc in this.subcatchments)
      {
        this.output.Add(
          string.Format(
            "{0,-16} {1,-18:F2} {2,-18:F2}",
            sc.SubcatchmentName,
            sc.Node.X + 10.0,
            sc.Node.Y + 10.0));
      }

      this.output.Add(string.Empty);
      this.output.Add("[CONDUITS]");
      this.output.Add(";;Conduit        From Node        To Node          Length     Roughness  InOffset   OutOffset  InitFlow   MaxFlow  ");
      this.output.Add(";;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ----------");
      foreach (ILink lk in model.Network.Links)
      {
        if (lk.USNode != null && lk.DSNode != null)
        {
          this.output.Add(string.Format("{0,-16} {1,-16} {2,-16} {3,-10:F1} {4,-10:F4} {5,-10:F2} {6,-10:F2} {7,-10:F2} {8,-10:F2}", lk.LinkName, lk.USNode.NodeName, lk.DSNode.NodeName, lk.LengthFt, .013, lk.USIEFt, lk.DSIEFt, 0.0, 0.0));
        }
      }

      this.output.Add(string.Empty);
      this.output.Add("[XSECTIONS]");
      this.output.Add(";;Link           Shape        Geom1            Geom2      Geom3      Geom4      Barrels   ");
      this.output.Add(";;-------------- ------------ ---------------- ---------- ---------- ---------- ----------");
      foreach (ILink lk in model.Network.Links)
      {
        //TODO: this is temporary remove when validation in place
        double dia;
        if (lk.HeightIn <= 0)
        {
          dia = 1.0;
        }
        else
        {
          dia = lk.HeightIn / 12.0;
        }

        this.output.Add(
          string.Format(
            "{0,-16} {1,-12} {2,-16:F3} {3,-10} {4,-10} {5,-10} {6,-10}", 
            lk.LinkName, 
            "CIRCULAR", 
            dia, 
            0.0, 
            0.0, 
            0.0, 
            1));
      }
    }

    /// <summary>
    /// Writes out the SWMM 5 file
    /// </summary>
    public void WriteSWMM5()
    {
      System.IO.File.WriteAllLines(@"C:\testdata\test.inp", this.output);
      ////System.IO.File.WriteAllLines(@"V:\9ESEN0000008\EMGAATS\SWMM5testing\test.inp", output);
    }
  }
}
